package eventBus0421

import (
	"sync"
	"sync/atomic"
	"time"
)

type Metrics struct {
	published int64
	dropped   int64
	mu        sync.Mutex
}

func (m *Metrics) IncPublished() {
	m.mu.Lock()
	m.published++
	m.mu.Unlock()
}

func (m *Metrics) IncDrop() {
	m.mu.Lock()
	m.dropped++
	m.mu.Unlock()
}

func (m *Metrics) Published() int64 {
	m.mu.Lock()
	defer m.mu.Unlock()
	return m.published
}

func (m *Metrics) Dropped() int64 {
	m.mu.Lock()
	defer m.mu.Unlock()
	return m.dropped
}


type TPSCounter struct {
	slots   []int64
	cursor  int
	window  int
	lastSec int64
	mu      sync.Mutex
}

func NewTPSCounter(windowSize int) *TPSCounter {
	return &TPSCounter{
		slots:  make([]int64, windowSize),
		window: windowSize,
	}
}

func (t *TPSCounter) Record() {
	t.mu.Lock()
	defer t.mu.Unlock()

	now := time.Now().Unix()
	if t.lastSec == 0 {
		t.lastSec = now
	}

	for t.lastSec < now {
		t.cursor = (t.cursor + 1) % t.window
		t.slots[t.cursor] = 0
		t.lastSec++
	}

	t.slots[t.cursor]++
}

func (t *TPSCounter) TPS(seconds int) int64 {
	t.mu.Lock()
	defer t.mu.Unlock()

	if seconds > t.window {
		seconds = t.window
	}
	var sum int64
	for i := 0; i < seconds; i++ {
		idx := (t.cursor - i + t.window) % t.window
		sum += t.slots[idx]
	}
	return sum / int64(seconds)
}

type workerManager struct {
	maxCPU int
	scale  func()
}

func newWorkerManager(cpu int, scaleFunc func()) *workerManager {
	return &workerManager{
		maxCPU: cpu * 2,
		scale:  scaleFunc,
	}
}

func (w *workerManager) Evaluate(queueLen int) {
	if queueLen > 100 {
		w.scale()
	}
}

func (b *Bus) WorkerCount() int {
	return int(atomic.LoadInt32(&b.workerCount))
}